<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    table,th,td{
      border: 1px solid black;
      border-collapse: collapse;
    }
    th,td{
      padding: 5px;
    }
  </style>
</head>
<!--
ajax
不刷新页面更新网页
在页面加载后从服务器请求数据
在页面加载后向服务器接收数据
在后台向服务器发送数据

AJAX  并非编程语言 仅仅组合了
浏览器内建的 XMLHttpRequest 对象 (从web服务器请求数据)
js 和 HTML DOM (显示或使用数据)

AJAX 应用程序可能使用xml 来传输数据 (JSON, XML, HTML, TXT 等)
ajax 允许通过与场景后面的web 服务器 交换数据来异步更新网页 ,意味着可以更新网页的部分 而不需要重新加载整个页面

ajax 如何工作
浏览器
发生某个事件,创建一个 XMLHttpRequest 对象 发送HTTP 请求

internet

服务器
处理 HTTP 请求 创建响应并将数据返回浏览器

internet

浏览器
使用 js处理被返回的数据
更新页面内容

1.网页中发生一个事件(页面加载,按钮点击)
2.由js创建一个 XMLHttpRequest 对象
3.xmlHttpRequest 对象向服务器发送请求
4.服务器处理该请求
5.服务器将相应发送回网页
6.由js 读取响应
7.由js 执行正确的动作 比较更新页面

xmlHttpRequest 对象 是ajax的基石
1.创建xmlHttpRequest 对象
2.定义回调函数
3.打开xmlHttpRequest 对象
4.向服务器发送请求

xmlHttpRequest 对象可用于后台于web服务器 交换数据 意味着可以更新网页的部分内容 而无需重新加载整个页面

创建xmlHttpRequest 对象
variable = new XMLHttpRequest();

定义回调函数 回调函数是作为参数传递给另一个函数的函数
回调函数应包含响应准备就绪时要执行的代码

xhttp.onload = function(){
  // 当响应准备就绪时要做什么
}

发送请求
可以使用 xmlHttpRequest 对象的 open() 和 send() 方法
xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();

跨域访问 出于安全原因,现代浏览器不允许跨域访问
这意味着网页和尝试加载的xml 文件必须位于同一台服务器上
new XMLHttpRequest()	创建新的 XMLHttpRequest 对象。
abort()	取消当前请求。
getAllResponseHeaders()	返回头部信息。
getResponseHeader()	返回特定的头部信息。
open(method, url, async, user, psw)
规定请求。

method：请求类型 GET 或 POST
url：文件位置
async：true（异步）或 false（同步）
user：可选的用户名
psw：可选的密码
send()	向服务器发送请求，用于 GET 请求。
send(string)	向服务器发送请求，用于 POST 请求。
setRequestHeader()	将标签/值对添加到要发送的标头。


onload	定义接收到（加载）请求时要调用的函数。
onreadystatechange	定义当 readyState 属性发生变化时调用的函数。
readyState
保存 XMLHttpRequest 的状态。

0：请求未初始化
1：服务器连接已建立
2：请求已收到
3：正在处理请求
4：请求已完成且响应已就绪
responseText	以字符串形式返回响应数据。
responseXML	以 XML 数据返回响应数据。
status
返回请求的状态号

200: "OK"
403: "Forbidden"
404: "Not Found"
如需完整列表请访问 Http 消息参考手册

statusText	返回状态文本（比如 "OK" 或 "Not Found"）

多个回调函数
loadDoc("url-1",myFunction1);
loadDoc("url-2",myFunction2);

function loadDoc(url, cFunction) {
  const xhttp = new XMLHttpRequest(); // 创建 XMLHttpRequest 对象
  xhttp.onload = function() {cFunction(this);} // 定义回调函数
  xhttp.open("GET", url); // 打开请求
  xhttp.send(); // 发送请求
}

// 定义回调函数
function myFunction1(xhttp) {
  // 这里是动作
}

// 定义回调函数
function myFunction2(xhttp) {
  // 这里是动作
}

onreadystatechange 属性  定义当 readyState 改变时执行该函数。
readyState 属性保存 XMLHttpRequest 的状态。
  0: 请求未初始化
  1: 服务器连接已建立
  2: 请求已接收
  3: 正在处理请求
  4: 请求已完成，且响应已就绪

onreadystatechange 属性定义了一个回调函数，当 readyState 改变时执行该函数。

status 属性和 statusText 属性保存 XMLHttpRequest 对象的状态。
  返回请求的状态号
  200: "OK"
  403: "Forbidden"
  404: "Not Found"

statusText 属性返回状态文本（比如 "OK" 或 "Not Found"）

每次readyState 属性改变时，onreadystatechange 事件被触发。
当 readyState 为 4 且status 为 200 时，响应就绪。

xmlHttpRequest 对象用于同服务器交换数据
向服务器发送请求
xhttp.open("GET", "ajax_info.txt", true);
  open (method,url,async)  method 请求类型 get 还是 post  url 服务器文件位置 async 异步还是同步 true 异步 false 同步
xhttp.send();
  向服务器发送请求 用于 GET 请求
send(string)
  向服务器发送请求 用于 POST 请求

使用post请求的情况
缓存文件不是选项 (更新服务器上的文件或数据库)
向服务器发送大量数据 (post无大小限制)
发送用户输入 (可包含未知字符) post比get更加强大更安全

异步 true 还是 false
如需 异步发送请求 open方法的async 参数设置为 true 或 false。默认为 true。
异步请求不会暂停浏览器的其它活动,这意味着可以在请求发送到服务器后继续执行其他脚本。
xhttp.open("GET", "ajax_info.txt", true);
发送异步请求 通过异步发送 js不必等待服务器响应 而可以
在等待服务器响应时执行其他脚本
当响应就绪时处理响应

onreadystatechange 属性
通过 XMLHttpRequest 对象，您可以定义当请求接收到应答时所执行的函数。

这个函数是在 XMLHttpResponse 对象的 onreadystatechange 属性中定义的：

同步请求
执行同步的请求 使用open 方法中的第三个参数设置为 false
xhttp.open("GET", "ajax_info.txt", false);")
有时async设置为false时,浏览器会等待响应,直到响应就绪,才继续执行脚本
由于代码将等待服务器完成 就不需要 onreadystatechange属性
不推荐同步的 XMLHttpRequest (async=false) 因为 js将停止执行知道服务器响应就绪  如果服务器繁忙缓慢,应用程序将挂起或停止

AJAX 用于创建更具交互性的应用程序

asp实例 用于创建更具交互性的应用程序
当用户输入字段中键入字符时 网页将发送请求到服务器，并显示从服务器返回的响应。


在上面的例子中，当用户在输入字段中键入字符时，会执行名为 "showHint()" 的函数。

此函数被 onkeyup 事件触发。
代码解释：
首先，检查输入字段是否为空（str.length == 0）；如果是，清空 txtHint 占位符的内容并退出函数。


不过，如果输入字段不为空，则进行如下：

创建 XMLHttpRequest 对象
创建当服务器响应就绪时执行的函数
发送请求到服务器上的 ASP 文件（gethint.asp）
请注意添加到 gethint.asp 的 q 参数
str 变量保存了输入字段的内容


-->
<body>
<h2>请在下面的输入字段中键入字母A-Z:</h2>
<P>搜索建议: <span id="tint"></span></P>
<p>姓名: <input type="text" id="txt2" onkeyup="showHint1(this.value)"> </p>

<script>
  function showHint1(str){
    var xhttp;
    if (str.length == 0) {
      document.getElementById("tint").innerHTML="";
      return;
    }
    xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        document.getElementById("tint").innerHTML = this.responseText;
      }
    };
    xhttp.open("GET", "./getHint.asp?q="+str, true);
    xhttp.send();
  }
</script>

<p>请在下面的输入字段中键入字母A-Z:</p>
<p>搜索建议: <span id="txtHint"></span> </p>
<p>姓名: <input type="text" id="txt1" onkeyup="showHint(this.value)"></p>



<!--代码解释：
首先，检查输入字段是否为空（str.length == 0），如果是，清空 txtHint 占位符的内容并退出函数。


不过，如果输入字段不为空，则进行如下：

创建 XMLHttpRequest 对象
创建当服务器响应就绪时执行的函数
发送请求到服务器上的 PHP 文件（gethint.php）
请注意添加到 gethint.php 的 q 参数
str 变量保存了输入字段的内容
-->

<script>
  function showHint(str) {
    var xhttp;
    if (str.length == 0) {
      document.getElementById("txtHint").innerHTML="";
      return;
    }
    xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        document.getElementById("txtHint").innerHTML = this.responseText;
      }
    };
    xhttp.open("GET", "./getHint.php?q="+str, true);
    xhttp.send();
  }
</script>
<!--显示来自服务器的信息-->
<div id="demo">
  <h1>ajax实例: 点击修改内容</h1>
<!--  调用函数 当它被点击时-->
  <button type="button" onclick="loadDoc()">修改内容</button>
</div>

<div id="demo1">
  <p>触发事件,被触发了四次(1-4),每次readyState变化一次</p>
  <button type="button" onclick="loadDoc1()">触发事件</button>
</div>

<div>
  <p>点击按钮几次查看时间是否已更改,或文件是否已缓存</p>
  <button type="button" onclick="loadDoc2()">请求数据</button>
  <p id="demo2"></p>
</div>

<div>
  <p>在网页中通过AJAX从xml文件读取信息</p>
  <button type="button" onclick="loadDoc3()">获取我的音乐列表</button>
  <br><br>
  <table id="demo3"></table>
</div>

<script>
  function loadDoc3() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        myFunction(this);
      }
    };
    xhttp.open("GET", "./music_list.xml", true);
    xhttp.send();
  }
  function myFunction(xml) {
    var i;
    var xmlDoc = xml.responseXML;
    var table="<tr><th>艺术家</th><th>曲目</th></tr>";
    var x = xmlDoc.getElementsByTagName("TRACK");
    for (i=0;i<x.length;i++){
      table += "<tr><td>" +
        x[i].getElementsByTagName("ARTIST")[0].childNodes[0].nodeValue +
        "</td><td>" +
        x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue +
        "</td></tr>";
    }
    document.getElementById("demo3").innerHTML = table;
  }
</script>

<script>
  function loadDoc2() {
    var xhttp = new XMLHttpRequest();
    // 定义当请求接收到应答时所执行的函数
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        document.getElementById("demo2").innerHTML =
          this.responseText;
      }
    };
    // 正常使用时
    xhttp.open("GET", "./demo_get.asp", true);
    // 避免缓存结果,可以向url添加一个唯一的id
    xhttp.open("GET", "./demo_get.asp?t="+Math.random(), true);
    // 传递参数
    xhttp.open("GET", "demo_get2.asp?fname=Bill&lname=Gates", true);
    // post请求
    xhttp.open("POST", "ajax_info.txt", true);
    // 如果需html 表单那样post 数据 请通过setRequestHeader() 添加一个HTTP头部,在send()方法中规定需要发送的数据
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send("fname=Bill&lname=Gates"); // 提交数据
  }
</script>


<script>
  function loadDoc1() {
    const xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState==4 && this.status == 200){
        document.getElementById("demo1").innerHTML = this.responseText;
      }
    };
    xhttp.open("GET", "ajax_info.txt", true);
    xhttp.send();
  }
</script>

<script>
  function loadDoc() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        document.getElementById("demo").innerHTML =
          this.responseText;
      }
    };
    xhttp.open("GET", "./ajax_info.txt", true);
    xhttp.send();
  }
</script>
</body>
</html>
